package controller;


import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import view.View;
import view._View;
import view.input.CommandInput;
import view.input.ContinuationInput;
import view.input.ConversationInput;
import view.input.InputWords;

import model.commands.CloseCommand;
import model.commands.Command;
import model.commands.GiveCommand;
import model.commands.GoCommand;
import model.commands.LookCommand;
import model.commands.MountCommand;
import model.commands.OpenCommand;
import model.commands.OrderCommand;
import model.commands.PickUpCommand;
import model.commands.TalkToCommand;
import model.conversations.ConversationManager;
import model.locations.Area;
import model.locations.World;
import model.locations._World;
import model.stageOfGame.StageManager;
import model.things.Thing;
import model.things.You;
import net.slashie.libjcsi.CSIColor;
import net.slashie.libjcsi.ConsoleSystemInterface;
import net.slashie.libjcsi.wswing.WSwingConsoleInterface;

import exceptions.CommandExecutionFail;
import exceptions.CommandInputNotValid;
import exceptions.InvalidCombination;
import exceptions.InvalidConversationNumber;
import exceptions.TalkToPerson;
import exceptions.ThingNotInArea;
import exceptions.TooManyWords;


public class Controller implements _Controller{
	
	ContinuationInput contInput;
	CommandInput comInput;
	ConversationInput convInput;
	ConversationManager conversationManager;
	int level=1;
	char stage='a';
	StageManager stageManager;
	
	String _command="command";
	String conversation="conversation";
	String changeLevel="changeLevel";

	String currentState= _command;
	_World world;
	
	_View view=new View(this);
	/////////////////////////////
	public ConsoleSystemInterface csi;
	/////////////////////////////
	
	//this variable is used to find the correct conversation number
	//The variable is incomplete as it needs conversation number
	String person;
	Command command;
	
	Map<String,Command> commandStore=new HashMap<String,Command>();
	
	public Controller(){
		contInput = new ContinuationInput();	
		comInput = new CommandInput();
		convInput = new ConversationInput();
		conversationManager =new ConversationManager();
		
		world =new World();
		view.printOutput("type \"o\" or \"objectives\" to view your objectives");
		
		stageManager=new StageManager(conversationManager, world);
		commandStore.put("GIVE",new GiveCommand(world));
		commandStore.put("TALKTO",new TalkToCommand(world));
		commandStore.put("ORDER",new OrderCommand(world));
		commandStore.put("MOUNT",new MountCommand(world));
		commandStore.put("PICKUP",new PickUpCommand(world));
		commandStore.put("LOOK",new LookCommand(world));
		commandStore.put("GO",new GoCommand(world));
		commandStore.put("OPEN",new OpenCommand(world));
		commandStore.put("CLOSE",new CloseCommand(world));
		
		/////////////////////////////////////////
		csi = null;
        try {
            csi = new WSwingConsoleInterface("FredGame - libjcsi example", true);
            csi.print(2,2,"Welcome to          - Make sure you can see this window when you type");
            csi.print(13,2,"FREDGAME",CSIColor.WHITE,CSIColor.ASPARAGUS);
        } catch (ExceptionInInitializerError eiie) {
            System.out.println("Fatal Error Initializing Swing Console Box");
            eiie.printStackTrace();
            System.exit(-1);
        }
        /////////////////////////////////////////
        try {
			conversationManager.loadConversationFromFile("saul1a.fgc");
		} catch (IOException e) {
			// TODO Auto-generated catch block
			System.out.println(System.getProperty("user.dir"));
			e.printStackTrace();
			
		}
	}


	/* (non-Javadoc)
	 * @see controller._Controller#start(java.lang.String)
	 */
	public void start(String input){
		
		System.out.println(input);
		
		if(currentState==conversation){	
			//checks to see whether conversation is complete
			if(goConversation(input))
			currentState=_command;
		}
		else if(currentState==_command){
			command(input);
			}
		else{
			changeLevel(input);
		}
	}

	/* (non-Javadoc)
	 * @see controller._Controller#command(java.lang.String)
	 */
	public void command(String input){
				
		InputWords words;
		
			try {		
					System.out.println(">");
					//InputWords words;
				
					words = comInput.getCommandWords(input);
					if(words.getWord1().toUpperCase().equals("O")||words.getWord1().toUpperCase().equals("OBJECTIVES")){
						view.printOutput(stageManager.getObjective());
					}
					else{
						Command command=commandStore.get(words.getWord1());
						String message=command.execute(words);
						view.printOutput(message);
					}
					if(world.getNextLevel()){
						currentState=changeLevel;
					}
					System.out.println(world);
				
				//the stage of the game is checked constantly
				stage =stageManager.updateCurrentStage();
				level=stageManager.getLevel();
				System.out.println("Level "+String.valueOf(level)+String.valueOf(stage));
			}
			catch (CommandExecutionFail e1) {
				view.printOutput("The word "+e1.getMessage()+" is not recognized");
				
			} catch (CommandInputNotValid e1) {
				view.printOutput("Not a vaild command");
				
			} catch (TooManyWords e1) {
				view.printOutput("Too many words!");
			}
			catch(TalkToPerson ex){
				person=ex.getConversationCode();
				currentState=conversation;
				selectConversation();
			} catch (InvalidCombination e9) {
				view.printOutput("You can't "+e9.getWord1()+" a "+e9.getWord2());
			}	
	}
	
	/* (non-Javadoc)
	 * @see controller._Controller#changeLevel(java.lang.String)
	 */
	public void changeLevel(String input){
		
		System.out.println("change level");
		InputWords words;
		words=convInput.paddyGetWords(input);
		System.out.println(input);
		if(words.getWord1().toUpperCase().equals("YES")||words.getWord1().toUpperCase().equals("Y")){
			
			if(stageManager.changeSetting()){
				world.changeSetting();
				view.printOutput("");
				view.newChapter();
			}
			else{
				view.printOutput("Sorry, you have not completed all of your objectives for this level yet");
			}
		}
		currentState=_command;
	}
	
	/* (non-Javadoc)
	 * @see controller._Controller#selectConversation()
	 */
	public void selectConversation(){
		try{
			view.printOutput(conversationManager.selectConversation(person,level,stage));
		}
		catch(InvalidConversationNumber ex){
			view.printOutput(person+" cannot speak to you now");
		}
	}
	
	/* (non-Javadoc)
	 * @see controller._Controller#goConversation(java.lang.String)
	 */
	public boolean goConversation(String input){
			
		boolean exit = false;
		InputWords words;
		
			System.out.print("> ");
			// Using my getwords
			words=convInput.paddyGetWords(input);
			view.printOutput(conversationManager.getReply(words));

			if(conversationManager.getStatusFinalReply()){
				System.out.println("finished conversation");
				
				exit=true;
			}	
		return exit;
	}
}
